/*
    文件内容: 封装EventLoop相关操作,封装Epoll,和while循环
    文件名: EventLoop.cpp
    作者: 中国好青年(码农论坛)
    时间: 2024/9/8

*/
#include "EventLoop.h"

/*  
    私有函数
    函数名: int EventLoop::createTimerFD(int time)
    返回值: 无
    参  数: 无
    函数作用: 创建timer的fd
    
*/
int EventLoop::createTimerFD(int sec)
{
    int tfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC|TFD_NONBLOCK);
    struct itimerspec timeout;
    memset(&timeout, 0, sizeof(struct itimerspec));
    timeout.it_value.tv_sec = sec;
    timeout.it_value.tv_nsec = 0;
    timerfd_settime(tfd, 0, &timeout, 0);
    return tfd;
}

/* 
    函数名: EventLoop(bool mainloop, int timeout, int timerval)
    返回值: 无
    参  数: bool mainloop,是否是主循环 int timeout,超时时间 int timerval,定时器间隔
    函数作用: 构造函数,创建Epoll对象
*/
EventLoop::EventLoop(bool mainloop, int timeout, int timerval)
                      :ep_(new Epoll),epolltimeoutval_(-1),mainloop_(mainloop),stop_(false)
                      ,timeout_(timeout),timerval_(timerval)
                      ,wakeupfd_(eventfd(0,EFD_NONBLOCK)),wakeupchannel_(new Channel(this, wakeupfd_))
                      ,timerfd_(createTimerFD(timerval)),timerchannel_(new Channel(this, timerfd_))
{
    wakeupchannel_ -> setReadCallback(std::bind(&EventLoop::handleWakeup, this));
    wakeupchannel_ -> enableReadEvent();
    if(mainloop_ == false)
    {
        timerchannel_ -> setReadCallback(std::bind(&EventLoop::handleTimer, this));
        timerchannel_ -> enableReadEvent();
    }

}

/* 
    函数名: ~EventLoop()
    返回值: 无
    参  数: 无
    函数作用: 析构函数,释放Epoll空间
*/
EventLoop::~EventLoop()
{   

}

/* 
    函数名: run()
    返回值: 无
    参  数: 无
    函数作用: 封装处理事件返回的业务
*/
void EventLoop::run()
{
    curlooppid_ = syscall(SYS_gettid);
    while(stop_ == false){
        std::vector<Channel*> evs = ep_ -> loop(epolltimeoutval_);
        if(evs.size() == 0)
        {
            if(epolltimeoutcallback_)
                epolltimeoutcallback_(this);
        }
        for(auto &ev : evs)
        {
          ev -> handleEvents();
        }
    }
}
/* 
    函数名: stop()
    返回值: 无
    参  数: 无
    函数作用: 封装处理事件返回的业务
*/
void EventLoop::stop()
{
    stop_ = true;
    wakeup(); //让epoll_wait返回
}
/* 
    函数名: updateChannel()
    返回值: 无
    参  数: 无
    函数作用: 封装Epoll中的updateChannel,让Channel对应到EventLoop
*/
void EventLoop::updateChannel(Channel *ch)
{
    ep_ -> updateChannel(ch);
}

/* 
    函数名: removeChannel(Channel *ch)
    返回值: 无
    参  数: 无
    函数作用: 封装Epoll中的updateChannel, 从epoll树删除
*/
void EventLoop::removeChannel(Channel *ch)
{
    ep_ -> removeChannel(ch);
}

/* 
    函数名: setepolltimeoutcallback(std::function<void(EventLoop*)> epolltimeoutcallback)
    返回值: 无
    参  数: 无
    函数作用: 设置epoll超时后的处理事件,在EchoServer中绑定
*/
void EventLoop::setepolltimeoutcallback(std::function<void(EventLoop*)> epolltimeoutcallback)
{
    epolltimeoutcallback_ = epolltimeoutcallback;
}

/*
    函数名: setEpollTimeoutVal(int timeout)
    返回值: 无
    参  数: int timeout 时间
    函数作用: 设置epoll超时机制
*/
void EventLoop::setEpollTimeoutVal(int timeout)
{
    epolltimeoutval_ = timeout;
}

/*
    函数名: setTimerCallback(std::function<void(int)> timercallback)
    返回值: 无
    参  数: timercallback, 函数对象
    函数作用: 设置定时器回调函数
*/
void EventLoop::setTimerCallback(std::function<void(int)> timercallback)
{
    timercallback_ = timercallback;
}

/*
    函数名: setEpollTimeoutVal(int timeout)
    返回值: bool,是否id相同
    参  数: 无
    函数作用: 是否线程id相同
*/
bool EventLoop::isEqualPid()
{
    return curlooppid_ == syscall(SYS_gettid);
}

/*
    函数名: addTaskQueue(std::function<void()> fn)
    返回值: bool,是否id相同
    参  数: 函数对象
    函数作用: 添加函数对象到队列
*/
void EventLoop::addTaskQueue(std::function<void()> fn)
{
    {
        std::lock_guard<std::mutex> lg(mutex_);
        taskqueue_.push(fn);
    }
    wakeup();
}

/*
    函数名: void EventLoop::wakeup()
    返回值: 无
    参  数: 无
    函数作用: 唤醒事件,处理队列中的事务
*/
void EventLoop::wakeup()
{
    uint64_t val = 1;
    write(wakeupfd_, &val, sizeof(val));
}

/*
    函数名: void EventLoop::handleWakeup()
    返回值: 无
    参  数: 无
    函数作用: 处理队列中的事件
*/
void EventLoop::handleWakeup()
{
    uint64_t val;
    read(wakeupfd_, &val, sizeof(val));
    
    std::function<void()> fn;

    std::lock_guard<std::mutex> lg(mutex_);
    while(taskqueue_.size() > 0)
    {
        fn = taskqueue_.front();
        taskqueue_.pop();
        fn();
    }
}

/*
    函数名: void EventLoop::handleTimer()
    返回值: 无
    参  数: 无
    函数作用: 处理定时器时间,事件
*/
void EventLoop::handleTimer()
{   
    
    struct itimerspec timeout;
    memset(&timeout, 0, sizeof(struct itimerspec));
    timeout.it_value.tv_sec = timerval_;
    timeout.it_value.tv_nsec = 0;
    timerfd_settime(timerfd_, 0, &timeout, 0);

    time_t now = time(0);
    debug("从reactor: ");
    for(auto it=conns.begin(); it != conns.end(); it++) 
    {   
       printf("%d ", it -> first);
       if(it->second->isTimeout(now, timeout_))
       {    
            std::lock_guard<std::mutex> lg(mutex_);
            conns.erase(it -> first);
       }   
       //处理tcpserver conns容器中的connecion对象
       if(timercallback_)
            timercallback_(it -> first);
    }
    printf("\n");
}

/*
    函数名: void EventLoop::newconnection(spConnection conn)
    返回值: 无
    参  数: 无
    函数作用: 新客户端连接上来后,添加到eventloop的map中
*/
 void EventLoop::newconnection(spConnection conn)
 {
    {
        std::lock_guard<std::mutex> lg(mutex_);
        conns[conn->fd()] = conn;
    }
 }